#ifndef MEMSTORAGE_HPP_
#define MEMSTORAGE_HPP_

//#include "filestorage.hpp"
#include <string>
#include "datastorage.hpp"
#include "filestorage.hpp"
#include <unordered_map>
#include <atomic>
#include <mutex>
#include <map>

using std::string;
using std::unordered_map;
using std::atomic;
using std::mutex;
using std::multimap;
using std::pair;
using std::make_pair;
using std::map;

class MemStorage : public DataStorage {
	public:
	MemStorage() = delete;
	MemStorage(size_t mem_size, size_t swap_size, const string& swap_path);
	~MemStorage();
	virtual DataChunk* alloc(size_t);
	
	inline bool haveChunk(DataChunk* chunk)
	{
		//lock_guard<mutex> lock(global_mutex_);
		//return chunks_all_.find(chunk) != chunks_all_.end(); //StackOverflows says that's safe...
		return std::find(chunks_all_.begin(), chunks_all_.end(), chunk) != chunks_all_.end(); //crapy but effective optimization...
	}
	
	private:
	virtual void free(DataChunk*);
	virtual char* get(DataChunk*);
	virtual void release(DataChunk*);
	
	inline pair<DataChunk* const, DataChunk*>* getChunkPair(DataChunk* chunk)
	{
		auto chunk_pair = chunks_.find(chunk);
		if (chunk_pair == chunks_.end()) {
			LOG_ERROR("no such chunk");
			throw MemAllocException(MemAllocException::E_INVAL);
		}
		return &(*chunk_pair);
	}
	inline void removeChunkPair(DataChunk* chunk)
	{
		// FIXME: Check find() != end()
		chunks_.erase(std::find(chunks_.begin(), chunks_.end(),	*getChunkPair(chunk)));
	}
	
	inline void appendChunkPair(DataChunk* mem_chunk, DataChunk* swap_chunk)
	{
		chunks_.insert(make_pair(mem_chunk, swap_chunk));
	}
	
	
	/*unordered_*/map<DataChunk*, DataChunk*> chunks_; //map search for ~O(1)
	multimap<size_t, char*> holes_;//map search lower_bound for ~O(sqrt(n))
	vector<DataChunk*> chunks_all_; // FIXME: Why vector? Free-s wil be very slow
	
	mutex global_mutex_;
	
	size_t total_allocated_; //FIXME service info
	char* data_;
	size_t data_size_;
	size_t data_free_;
	size_t data_pos_;
	FileStorage* swap_; //not only FileStorage - any suitable DataStorage

};

#endif //MEMSTORAGE_HPP_
